package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.entity.Borrower;
import com.atguigu.srb.core.entity.BorrowerAttach;
import com.atguigu.srb.core.entity.UserInfo;
import com.atguigu.srb.core.entity.UserIntegral;
import com.atguigu.srb.core.entity.vo.ApprovalForm;
import com.atguigu.srb.core.entity.vo.BorrowerDetailVo;
import com.atguigu.srb.core.entity.vo.BorrowerVo;
import com.atguigu.srb.core.mapper.BorrowerMapper;
import com.atguigu.srb.core.mapper.DictMapper;
import com.atguigu.srb.core.service.BorrowerAttachService;
import com.atguigu.srb.core.service.BorrowerService;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 借款人 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2023-06-30
 */
@Service
public class BorrowerServiceImpl extends ServiceImpl<BorrowerMapper, Borrower> implements BorrowerService {
    @Resource
    private UserInfoService userInfoService;
    @Resource
    BorrowerAttachService borrowerAttachService;
    @Resource
    DictMapper dictMapper;
    @Resource
    UserIntegralServiceImpl userIntegralService;
    //设置到多个数据库的insert业务,需要开启事务功能
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void processData(String token, BorrowerVo borrowerVo) {
        //1.先获取到用户的userId
        Long userId = JwtUtils.getUserId(token);
        //根据用户的userId,查询获取userInfo
        UserInfo userInfo = userInfoService.getById(userId);
        //准备一个新的Borrower对象
        Borrower borrower = new Borrower();
        //复制属性
        BeanUtils.copyProperties(borrowerVo,borrower);
        //2.设置user_id,name,id_card,mobile,status这几个属性
        //状态（0：未认证，1：认证中， 2：认证通过， -1：认证失败）
        borrower.setName(userInfo.getName());
        borrower.setUserId(userId);
        borrower.setIdCard(userInfo.getIdCard());
        borrower.setMobile(userInfo.getMobile());
        borrower.setStatus(1);
        //保存借款人信息到数据库中
        this.save(borrower);
        //3.保存借款人的附件表格
        borrowerVo.getBorrowerAttaches().forEach(borrowerAttach -> {
            borrowerAttach.setBorrowerId(borrower.getId());
        });
        borrowerAttachService.saveBatch(borrowerVo.getBorrowerAttaches());
    }

    @Override
    public Integer getStatus(String token) {
        //根据token获取userId
        Long userId = JwtUtils.getUserId(token);
        //根据userId查询借款人借款申请的状态
        Borrower one = this.getOne(Wrappers.lambdaQuery(Borrower.class).eq(Borrower::getUserId, userId)
                .select(Borrower::getStatus));
        //如果查询出来的结果为null,那么说明还没有申请,直接给0返回
        return one == null ? 0:one.getStatus();
    }

    //带分页条件的查询
    @Override
    public Page<Borrower> listPage(Integer pageNum, Integer pageSize, String keyword) {
        //创建page对象
        Page<Borrower> borrowerPage = new Page<>(pageNum, pageSize);
        //创建查询条件
        LambdaQueryWrapper<Borrower> wrapper = Wrappers.lambdaQuery(Borrower.class);
        //创建查询的条件
        if(StringUtils.isNotEmpty(keyword)){
            //进来这里面说明查询条件不为空, 需要拼接查询的条件
            wrapper.like(Borrower::getName,keyword)
                    .or().like(Borrower::getMobile,keyword)
                    .or().like(Borrower::getIdCard,keyword);
        }
        Page<Borrower> page = this.page(borrowerPage, wrapper);
        return page;
    }

    //根据borrowerId查询borrowerVo的详情
    @Override
    public BorrowerDetailVo getDetail(Long borrowerId) {
        //首先要根据borrowerId查询出来该借款人相关的所有信息
        Borrower borrower = this.getById(borrowerId);
        //将borrower里面的属性赋值到borrowerDetailVo对象里面
        BorrowerDetailVo borrowerDetailVo = new BorrowerDetailVo();
        BeanUtils.copyProperties(borrower,borrowerDetailVo);
        //将该借款人相关的附件查询出来设置到对象里面
        List<BorrowerAttach> list = borrowerAttachService.list(Wrappers.lambdaQuery(BorrowerAttach.class)
                .eq(BorrowerAttach::getBorrowerId, borrowerId));
        borrowerDetailVo.setBorrowerAttaches(list);
        //完成map里面对应的属性值的赋值(需要根据dictCode和value来查询对应的dict的name)
        Map<String, String> params = borrowerDetailVo.getParams();
        //设置申请的状态 状态（0：未认证，1：认证中， 2：认证通过， -1：认证失败）
        Integer integerStatus = borrowerDetailVo.getStatus();
        String status = getStatus(integerStatus);
        params.put("status",status);

        //性别和是否结婚
        params.put("sex",borrowerDetailVo.getSex() == 1 ? "男":"女");
        params.put("marry",borrowerDetailVo.getMarry() ? "是":"否");

            //学历
            // setParams(borrowerDetailVo, params,"education");
            String education = dictMapper.getDictNameByDictCodeAndValue("education",borrowerDetailVo.getEducation());
            params.put("education",education);
            //月收入
            String income = dictMapper.getDictNameByDictCodeAndValue("income",borrowerDetailVo.getIncome());
            params.put("income",income);
            //行业
            // setParams(borrowerDetailVo, params,"industry");
            String industry = dictMapper.getDictNameByDictCodeAndValue("industry",borrowerDetailVo.getIndustry());
            params.put("industry",industry);
            //还款来源
            // setParams(borrowerDetailVo, params,"returnSource");
            String returnSource = dictMapper.getDictNameByDictCodeAndValue("returnSource",borrowerDetailVo.getReturnSource());
            params.put("returnSource",returnSource);
            //联系人关系
            // setParams(borrowerDetailVo, params,"contactsRelation");
            String contactsRelation = dictMapper.getDictNameByDictCodeAndValue("relation",borrowerDetailVo.getContactsRelation());
            params.put("contactsRelation",contactsRelation);

            return borrowerDetailVo;
    }

    //根据userId查询borrowerVo的详情
    @Override
    public BorrowerDetailVo getDetailByUserId(Long userId) {
        //根据userId查询出来对应的borrower对象
        Borrower borrower = this.getOne(Wrappers.lambdaQuery(Borrower.class).eq(Borrower::getUserId,userId));
        //将borrower里面的属性赋值到borrowerDetailVo对象里面
        BorrowerDetailVo borrowerDetailVo = new BorrowerDetailVo();
        BeanUtils.copyProperties(borrower,borrowerDetailVo);
        //将该借款人相关的附件查询出来设置到对象里面
        //这里面不需要附件的信息,所以这一步可以省略
        /* List<BorrowerAttach> list = borrowerAttachService.list(Wrappers.lambdaQuery(BorrowerAttach.class)
                .eq(BorrowerAttach::getBorrowerId, borrowerId));
        borrowerDetailVo.setBorrowerAttaches(list); */
        //完成map里面对应的属性值的赋值(需要根据dictCode和value来查询对应的dict的name)
        Map<String, String> params = borrowerDetailVo.getParams();
        //设置申请的状态 状态（0：未认证，1：认证中， 2：认证通过， -1：认证失败）
        Integer integerStatus = borrowerDetailVo.getStatus();
        String status = getStatus(integerStatus);
        params.put("status",status);

        //性别和是否结婚
        params.put("sex",borrowerDetailVo.getSex() == 1 ? "男":"女");
        params.put("marry",borrowerDetailVo.getMarry() ? "是":"否");

        //学历
        // setParams(borrowerDetailVo, params,"education");
        String education = dictMapper.getDictNameByDictCodeAndValue("education",borrowerDetailVo.getEducation());
        params.put("education",education);
        //行业
        // setParams(borrowerDetailVo, params,"industry");
        String industry = dictMapper.getDictNameByDictCodeAndValue("industry",borrowerDetailVo.getIndustry());
        params.put("industry",industry);
        //月收入
        String income = dictMapper.getDictNameByDictCodeAndValue("income",borrowerDetailVo.getIncome());
        params.put("income",income);
        //还款来源
        // setParams(borrowerDetailVo, params,"returnSource");
        String returnSource = dictMapper.getDictNameByDictCodeAndValue("returnSource",borrowerDetailVo.getReturnSource());
        params.put("returnSource",returnSource);
        //联系人关系
        // setParams(borrowerDetailVo, params,"contactsRelation");
        String contactsRelation = dictMapper.getDictNameByDictCodeAndValue("relation",borrowerDetailVo.getContactsRelation());
        params.put("contactsRelation",contactsRelation);

        return borrowerDetailVo;
    }

    //审核借款人的信息
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approval(ApprovalForm approvalForm) {
        //根据借款人id获取用户id
        Borrower borrower = this.getById(approvalForm.getBorrowerId());
        Long userId = borrower.getUserId();

        //4.根据借款人审批的状况(-1不通过,2通过),将借款人的状态更新为对应的值 状态（0：未认证，1：认证中， 2：认证通过， -1：认证失败）
        this.update(Wrappers.lambdaUpdate(Borrower.class).eq(Borrower::getId,approvalForm.getBorrowerId())
                .set(Borrower::getStatus,approvalForm.getStatus())
                .set(Borrower::getUpdateTime,new Date()));
        if(approvalForm.getStatus() != 2){
            //如果不为2,说明认证失败,后面的步骤不用执行了,直接Return即可
            return;
        }
        //1.计算每项的审核后的积分情况,并计算借款人总的积分
        List<UserIntegral> userIntegrals = new ArrayList<>();
        int totalGrades = 0;
        //1.1基本信息
        //1.1.1基本总积分加上基本信息积分
        totalGrades += approvalForm.getInfoIntegral();
        //1.1.2创建userIntegral对象
        UserIntegral infoIntegral = new UserIntegral();
        //1.1.3设置userIntegral对象的integral属性
        infoIntegral.setIntegral(approvalForm.getInfoIntegral());
        //1.1.4设置userIntegral对象的userId属性
        infoIntegral.setUserId(userId);
        //1.1.5设置userIntegral对象的content属性
        infoIntegral.setContent("借款人基本信息积分");
        userIntegrals.add(infoIntegral);

        //1.2身份证认证信息
        if(approvalForm.getIsIdCardOk()){
            //身份证认证通过,获得30积分
            totalGrades += 30;
            UserIntegral idCardIntegral = new UserIntegral();
            idCardIntegral.setUserId(userId);
            idCardIntegral.setIntegral(30);
            idCardIntegral.setContent("借款人身份认证积分");
            userIntegrals.add(idCardIntegral);
        }
        //1.3车辆认证信息
        if(approvalForm.getIsCarOk()){
            totalGrades += 60;
            UserIntegral carIntegral = new UserIntegral();
            carIntegral.setUserId(userId);
            carIntegral.setIntegral(60);
            carIntegral.setContent("借款人车辆认证积分");
            userIntegrals.add(carIntegral);
        }
        //1.4房产认证信息
        if(approvalForm.getIsHouseOk()){
            totalGrades += 100;
            UserIntegral houseIntegral = new UserIntegral();
            houseIntegral.setUserId(userId);
            houseIntegral.setIntegral(100);
            houseIntegral.setContent("借款人房产认证积分");
            userIntegrals.add(houseIntegral);
        }
        //2.将每项的积分情况批量插入到user_integral表中
        userIntegralService.saveBatch(userIntegrals);
        //3.将总的积分更新到user_info表里面
        /* userInfoService.update(Wrappers.lambdaUpdate(UserInfo.class)
                .eq(UserInfo::getId,userId)
                //这个地方更新积分的时候,还需要加上原有的积分,所以使用lambdaWrapper的方式没法实现这个功能
                //必须得先将userInfo查询出来,再更新integral积分情况
                .set(UserInfo::getIntegral,totalGrades)
                .set(UserInfo::getUpdateTime,new Date())); */
        UserInfo userInfo = userInfoService.getById(userId);
        userInfo.setIntegral(userInfo.getIntegral() + totalGrades);
        userInfoService.updateById(userInfo);
    }

    private String getStatus(Integer integerStatus) {
        String stringStatus = null;
        switch(integerStatus){
            case 0:
                stringStatus = "未认证";
                break;
            case 1:
                stringStatus = "认证中";
                break;
            case 2:
                stringStatus = "认证通过";
                break;
            default:
                stringStatus = "认证失败";
                break;
        }
        return stringStatus;
    }

    private void setParams(BorrowerDetailVo borrowerDetailVo, Map<String, String> params,String label) throws InvocationTargetException, IllegalAccessException {
        String valueName = dictMapper.getDictNameByDictCodeAndValue(label, (Integer) getMethod(label,BorrowerDetailVo.class).invoke(null));
        params.put(label,valueName);
    }

    //利用反射获取对应属性的get方法
    private Method getMethod(String methodName, Class<BorrowerDetailVo> clz){
        String substring = methodName.substring(1);
        //首先获取所有的声明过的方法
        /* List<Method> collect = Arrays.stream(clz.getDeclaredMethods()).filter(m -> m.getName().contains(substring)).collect(Collectors.toList());
        return collect.get(0); */
        Method[] methods = clz.getMethods();
        for (int i = 0; i < methods.length; i++) {
            if(methods[i].getName().contains(substring)){
                methods[i].setAccessible(true);
                return methods[i];
            }
        }
        return null;
    }
}
